/*
 * CurrentOptions.cpp
 *
 *  Created on: 17 июн. 2022 г.
 *      Author: nikita
 */

#include "CurrentOptions.h"

namespace STC_calc
{
/*
	std::list<std::shared_ptr<MVariable>> var_params = {};

CurrentOptions::Variable_params::Variable_params(std::string name, long double min, long double max, long double steps)
{
	this->variable_name = name;
	this->range = std::pair<long double, long double>(min, max);
	this->number_of_steps = steps;
}
CurrentOptions::Variable_params::Variable_params(const Variable_params& A)
{
	this->variable_name = A.variable_name;
	this->range = A.range;
	this->number_of_steps = A.number_of_steps;
}
CurrentOptions::Variable_params::~Variable_params()
{

}
void CurrentOptions::Variable_params::operator =(const Variable_params& A)
{
	this->variable_name = A.variable_name;
	this->range = A.range;
	this->number_of_steps = A.number_of_steps;
}*/

CurrentOptions::CurrentOptions(const Modes mode, const std::string& execution_str, const string_vector& flags_up)
{
    this->current_mode = {mode, false};

    this->string_for_execution = {execution_str, true};
    if (execution_str.empty()) this->string_for_execution.second = false;

    for (auto s : flags_up) set_flag(s);
}
CurrentOptions::~CurrentOptions(){}

CurrentOptions::CurrentOptions(const CurrentOptions& A)
:
CurrentOptions(A.current_mode, A.string_for_execution)
{
	flags = A.flags;
}

bool CurrentOptions::get_flag(const std::string& flag_name)
{
	if (flags.find(flag_name) == flags.end()) return false;
	return true;
}

void CurrentOptions::set_exe_string(const std::string& func)
{
    if (!string_for_execution.second) throw (RuntimeErrorClass("Redefenition of exe function"));
    string_for_execution = {func, true};
}
bool CurrentOptions::is_func_empty()
{
    return !string_for_execution.second;
}

void CurrentOptions::add_variable(const string_list& args)
{
    string_list arguments = args;
    std::pair<long double, long double> range;
    long double steps;
    ldouble_vector answ(3);

    std::string name = arguments.front;
    arguments.pop_front();

    for (int i = 0; i < 2; ++i)
    {
        auto subfunction = SemanticAnalyzer::define_subfunction(arguments);
        arguments = subfunction.second;
        auto convert = SemanticAnalyzer::try_convert(subfunction.first);
        if (convert.second)
        {
            answ[i] = SemanticAnalyzer::convert(convert.first).front();
            continue;
        }
        answ[i] = TerminalMainClass::start_subprocess(args);
    }
    range.first = answ[0];
    range.second = answ[1];
    steps = answ[2];
    add_variable(name, range.first, range.second, steps);
}
void CurrentOptions::add_variable(const std::shared_ptr<MVariable> var)
{
	auto a = var;
    if (is_const(var->name)||is_var(var->name)) throw (RuntimeErrorClass("Already exists variable or constant with name " + name));
	var_params.insert({var->name(), a});
}
void CurrentOptions::add_variable(const std::string& name, const long double min, const long double max, const long double steps)
{
    add_variable(std::make_shared<MVariable>({name, min, max, steps}));
}

void CurrentOptions::add_constant(const string_list& args)
{
    string_list arguments = args;
    long double answ;

    std::string name = arguments.front;
    arguments.pop_front();

    auto subfunction = SemanticAnalyzer::define_subfunction(arguments);
    arguments = subfunction.second;
    auto convert = SemanticAnalyzer::try_convert(subfunction.first);
    if (convert.second)
    {
        answ = SemanticAnalyzer::convert(convert.first).front();
        continue;
    }
    answ = TerminalMainClass::start_subprocess(args);
    add_constant(name, answ);
}
void CurrentOptions::add_constant(const std::shared_ptr<MVariable> var)
{
    auto a = var;
    if (is_const(var->name)||is_var(var->name)) throw (RuntimeErrorClass("Already exists variable or constant with name " + name));
    const_params.insert({var->name(), a});
}
void CurrentOptions::add_constant(const std::string& name, const long double value)
{
    add_constant(std::make_shared<MConstant>({name, value}));
}

void CurrentOptions::set_mode(const Modes mode)
{
    current_mode = {mode, true};
}
bool CurrentOptions::is_var(const std::string& str)
{
    return var_params.find(str) == var_params.end();
}

bool CurrentOptions::is_const(const std::string& str)
{
    return const_params.find(str) == const_params.end();
}

std::pair<std::shared_ptr<MVariable>, bool> CurrentOptions::get_variable(const std::string& name)
{
    if (var_params.find(name) == var_params.end()) return {nullptr, false};
    return {var_params.at(name), true};
}

std::pair<std::shared_ptr<MConstant>, bool> CurrentOptions::get_constant(const std::string& name)
{
    if (const_params.find(name) == const_params.end()) return {nullptr, false};
    return {const_params.at(name), true};
}

void CurrentOptions::set_flag(const std::string& flag_name)
{
	flags.insert(flag_name);
}

} /* namespace STC_calc */
